package com.supreme.threadserver.config;

import com.supreme.threadserver.handler.ThreadPoolRejectStrategy;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

@Data
@EnableAsync
@Configuration
@ConfigurationProperties(prefix = "thread-pool")
public class ThreadPoolTaskConfig {

    public static final String TASK_EXECUTOR = "taskExecutor";
    public static final String SUPREME_TASK_EXECUTOR = "supremeTaskExecutor";

    public static final String MING_TASK_EXECUTOR = "mingTaskExecutor";

    private Integer corePoolSize;
    private Integer maxPoolSize;
    private Integer queueCapacity;
    private Integer keepAliveSeconds;
    private String threadNamePrefix;
    private String rejectedClassName;

    @Bean(value = TASK_EXECUTOR)
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setThreadNamePrefix("spring-task-");
        return threadPoolTaskExecutor;
    }

    @Bean(value = SUPREME_TASK_EXECUTOR)
    public ThreadPoolTaskExecutor supremeTaskExecutor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setQueueCapacity(queueCapacity);

        // 设置允许的空闲时间（秒）
        taskExecutor.setKeepAliveSeconds(keepAliveSeconds);

        // 设置默认线程名称
        taskExecutor.setThreadNamePrefix(threadNamePrefix);

        // 设置拒绝策略rejection-policy：当pool已经达到max size的时候，如何处理新任务
        Class<?> clazz = Class.forName(rejectedClassName);
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
//        Constructor<?> constructor = ReflectionUtils.accessibleConstructor(clazz);
        Object rejectStrategy = constructor.newInstance();
        if (rejectStrategy instanceof RejectedExecutionHandler) {
            RejectedExecutionHandler rejectedExecutionHandler = (RejectedExecutionHandler) constructor.newInstance();
            taskExecutor.setRejectedExecutionHandler(rejectedExecutionHandler);
        }

        // 等待所有任务结束后在关闭线程池
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
//        taskExecutor.initialize();

        return taskExecutor;
    }

    @Bean(value = MING_TASK_EXECUTOR)
    public ThreadPoolTaskExecutor mingTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(2);
        taskExecutor.setMaxPoolSize(4);
        taskExecutor.setQueueCapacity(10);
        taskExecutor.setKeepAliveSeconds(1);
        taskExecutor.setThreadNamePrefix("ming-task-");
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolRejectStrategy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        return taskExecutor;
    }
}
